<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>缓存管理 - 权限事务缓存系统</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body {
            background-color: #f8f9fa;
        }
        .card {
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
        .table th, .table td {
            vertical-align: middle;
        }
        .pagination .page-item .page-link {
            border-radius: 4px;
            margin: 0 2px;
        }
        .pagination .page-item.active .page-link {
            background-color: #6a11cb;
            border-color: #6a11cb;
        }
        .code-block {
            background-color: #f1f3f4;
            padding: 10px;
            border-radius: 4px;
            font-family: monospace;
            word-break: break-all;
            max-height: 200px;
            overflow-y: auto;
        }
    </style>
</head>
<body>
    <!-- 导航栏 -->
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
            <a class="navbar-brand" href="javascript:window.location.href = '/' + window.location.pathname.split('/')[1]">权限事务缓存系统</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item">
                        <a class="nav-link" href="javascript:window.location.href = '/' + window.location.pathname.split('/')[1]">首页</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="javascript:window.location.href = '/' + window.location.pathname.split('/')[1] + '/users'">用户管理</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="javascript:window.location.href = '/' + window.location.pathname.split('/')[1] + '/roles'">角色管理</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="javascript:window.location.href = '/' + window.location.pathname.split('/')[1] + '/permissions'">权限管理</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link active" href="javascript:location.reload()">缓存管理</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>

    <!-- 主要内容 -->
    <div class="container my-5">
        <div class="card">
            <div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
                <h4 class="mb-0">缓存管理</h4>
                <button type="button" class="btn btn-light btn-sm" data-bs-toggle="modal" data-bs-target="#setCacheModal">
                    设置缓存
                </button>
            </div>
            <div class="card-body">
                <!-- 搜索和操作区域 -->
                <div class="row mb-4">
                    <div class="col-md-6 mb-3">
                        <div class="input-group">
                            <input type="text" id="searchKeyInput" class="form-control" placeholder="搜索缓存键">
                            <button class="btn btn-outline-secondary" type="button" id="searchCacheButton">查询缓存</button>
                        </div>
                    </div>
                    <div class="col-md-6 mb-3 d-flex gap-2">
                        <div class="input-group flex-grow-1">
                            <input type="text" id="clearPrefixInput" class="form-control" placeholder="输入前缀以清除相关缓存">
                            <button class="btn btn-outline-warning" type="button" id="clearPrefixButton">清除前缀缓存</button>
                        </div>
                        <button class="btn btn-danger" type="button" id="clearAllCacheButton">
                            清空所有缓存
                        </button>
                    </div>
                </div>

                <!-- 缓存列表表格 -->
                <div class="table-responsive">
                    <table class="table table-hover">
                        <thead>
                            <tr class="bg-light">
                                <th scope="col">缓存键</th>
                                <th scope="col">缓存值</th>
                                <th scope="col">过期时间(秒)</th>
                                <th scope="col">是否存在</th>
                                <th scope="col">操作</th>
                            </tr>
                        </thead>
                        <tbody id="cacheTableBody">
                            <!-- 缓存数据将通过JavaScript动态加载 -->
                            <tr id="cacheExampleRow" style="display: none;">
                                <td id="exampleCacheKey">user:123</td>
                                <td id="exampleCacheValue">
                                    <div class="code-block">{"id":123,"name":"张三","age":30}</div>
                                </td>
                                <td id="exampleExpireTime">3600</td>
                                <td id="exampleExists">
                                    <span class="badge bg-success">是</span>
                                </td>
                                <td>
                                    <button class="btn btn-sm btn-outline-primary me-2 get-cache" data-key="user:123">获取详情</button>
                                    <button class="btn btn-sm btn-outline-warning me-2 set-expire" data-key="user:123">设置过期时间</button>
                                    <button class="btn btn-sm btn-outline-danger delete-cache" data-key="user:123">删除缓存</button>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>

                <!-- 缓存监控信息 -->
                <div class="row mt-5">
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-header bg-info text-white">
                                <h5 class="mb-0">缓存使用建议</h5>
                            </div>
                            <div class="card-body">
                                <ul class="list-unstyled">
                                    <li class="mb-2">• 缓存键应使用统一格式，如 module:id</li>
                                    <li class="mb-2">• 为缓存设置合理的过期时间，避免缓存雪崩</li>
                                    <li class="mb-2">• 敏感数据不建议缓存或需加密存储</li>
                                    <li class="mb-2">• 缓存值不宜过大，建议小于1MB</li>
                                    <li>• 数据更新时及时清除相关缓存，保证数据一致性</li>
                                </ul>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="card">
                            <div class="card-header bg-success text-white">
                                <h5 class="mb-0">缓存键前缀示例</h5>
                        </div>
                        <div class="card-body">
                                <ul class="list-unstyled">
                                    <li class="mb-2">• user: - 用户相关缓存</li>
                                    <li class="mb-2">• role: - 角色相关缓存</li>
                                    <li class="mb-2">• permission: - 权限相关缓存</li>
                                    <li class="mb-2">• config: - 系统配置缓存</li>
                                    <li>• session: - 用户会话缓存</li>
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 设置缓存模态框 -->
    <div class="modal fade" id="setCacheModal" tabindex="-1" aria-labelledby="setCacheModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="setCacheModalLabel">设置缓存</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <form id="setCacheForm">
                        <div class="mb-3">
                            <label for="cacheKey" class="form-label">缓存键 *</label>
                            <input type="text" class="form-control" id="cacheKey" required placeholder="如: user:123">
                        </div>
                        <div class="mb-3">
                            <label for="cacheValue" class="form-label">缓存值 *</label>
                            <textarea class="form-control" id="cacheValue" rows="4" required placeholder="缓存的值内容"></textarea>
                            <div class="form-text">JSON格式的数据会自动格式化显示</div>
                        </div>
                        <div class="mb-3">
                            <label for="cacheExpire" class="form-label">过期时间(秒)</label>
                            <input type="number" class="form-control" id="cacheExpire" min="0" placeholder="不设置则永不过期">
                            <div class="form-text">常用时间：3600(1小时), 86400(1天), 604800(7天)</div>
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="button" class="btn btn-primary" id="saveCacheButton">保存缓存</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 获取缓存详情模态框 -->
    <div class="modal fade" id="cacheDetailModal" tabindex="-1" aria-labelledby="cacheDetailModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="cacheDetailModalLabel">缓存详情</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <input type="hidden" id="detailCacheKey">
                    <div class="mb-3">
                        <label class="form-label">缓存键</label>
                        <p id="detailKeyDisplay" class="form-control-plaintext font-weight-bold"></p>
                    </div>
                    <div class="mb-3">
                        <label class="form-label">缓存值</label>
                        <div id="detailValueDisplay" class="code-block"></div>
                    </div>
                    <div class="row">
                        <div class="col-md-6 mb-3">
                        <label class="form-label">过期时间(秒)</label>
                        <p id="detailExpireDisplay" class="form-control-plaintext"></p>
                    </div>
                        <div class="col-md-6 mb-3">
                        <label class="form-label">存在状态</label>
                        <p id="detailExistsDisplay" class="form-control-plaintext"></p>
                    </div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-outline-warning me-2" id="updateExpireButton">更新过期时间</button>
                    <button type="button" class="btn btn-danger me-2" id="deleteFromDetailButton">删除缓存</button>
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 设置过期时间模态框 -->
    <div class="modal fade" id="setExpireModal" tabindex="-1" aria-labelledby="setExpireModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="setExpireModalLabel">设置过期时间</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <input type="hidden" id="expireCacheKey">
                    <div class="mb-3">
                        <label class="form-label">缓存键</label>
                        <p id="expireKeyDisplay" class="form-control-plaintext font-weight-bold"></p>
                    </div>
                    <div class="mb-3">
                        <label for="newExpireTime" class="form-label">新的过期时间(秒) *</label>
                        <input type="number" class="form-control" id="newExpireTime" required min="0" placeholder="不设置则永不过期">
                        <div class="form-text">常用时间：3600(1小时), 86400(1天), 604800(7天)</div>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="button" class="btn btn-primary" id="confirmExpireButton">确认设置</button>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        // 获取上下文路径
        const contextPath = window.location.pathname.split('/')[1];
        const baseUrl = '/' + contextPath;
        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', function() {
            // 显示示例缓存数据
            const exampleRow = document.getElementById('cacheExampleRow');
            exampleRow.style.display = 'table-row';
            
            // 搜索缓存按钮事件
            document.getElementById('searchCacheButton').addEventListener('click', function() {
                const key = document.getElementById('searchKeyInput').value.trim();
                if (!key) {
                    alert('请输入缓存键');
                    return;
                }
                
                // 显示加载中状态
                const tableBody = document.getElementById('cacheTableBody');
                tableBody.innerHTML = `
                    <tr>
                        <td colspan="5" class="text-center">
                            <div class="spinner-border" role="status">
                                <span class="visually-hidden">查询中...</span>
                            </div>
                        </td>
                    </tr>
                `;
                
                // 查询缓存
                fetchCache(key);
            });
            
            // 按Enter键搜索
            document.getElementById('searchKeyInput').addEventListener('keyup', function(event) {
                if (event.key === 'Enter') {
                    document.getElementById('searchCacheButton').click();
                }
            });
            
            // 清除前缀缓存按钮事件
            document.getElementById('clearPrefixButton').addEventListener('click', function() {
                const prefix = document.getElementById('clearPrefixInput').value.trim();
                if (!prefix) {
                    alert('请输入缓存前缀');
                    return;
                }
                
                if (confirm(`确定要清除所有前缀为「${prefix}」的缓存吗？`)) {
                    fetch(`${baseUrl}/api/cache/prefix/${encodeURIComponent(prefix)}`, {
                        method: 'DELETE'
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.code === 200) {
                            alert('缓存清除成功');
                            document.getElementById('clearPrefixInput').value = '';
                        } else {
                            alert('清除失败: ' + (data.message || '未知错误'));
                        }
                    })
                    .catch(error => {
                        console.error('清除缓存失败:', error);
                        alert('清除失败: 网络错误');
                    });
                }
            });
            
            // 清空所有缓存按钮事件
            document.getElementById('clearAllCacheButton').addEventListener('click', function() {
                if (confirm('确定要清空所有缓存吗？此操作不可恢复！')) {
                    fetch(`${baseUrl}/api/cache`, {
                        method: 'DELETE'
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.code === 200) {
                            alert('所有缓存已清空');
                            // 清空表格
                            const tableBody = document.getElementById('cacheTableBody');
                            tableBody.innerHTML = '';
                        } else {
                            alert('清空失败: ' + (data.message || '未知错误'));
                        }
                    })
                    .catch(error => {
                        console.error('清空缓存失败:', error);
                        alert('清空失败: 网络错误');
                    });
                }
            });
            
            // 保存缓存按钮事件
            document.getElementById('saveCacheButton').addEventListener('click', function() {
                const key = document.getElementById('cacheKey').value.trim();
                const value = document.getElementById('cacheValue').value.trim();
                const expireStr = document.getElementById('cacheExpire').value.trim();
                
                if (!key || !value) {
                    alert('请填写缓存键和缓存值');
                    return;
                }
                
                const expire = expireStr ? parseInt(expireStr) : null;
                
                // 构建缓存数据
                const cacheData = {
                    key: key,
                    value: value
                };
                
                if (expire !== null && expire >= 0) {
                    cacheData.expire = expire;
                }
                
                fetch(`${baseUrl}/api/cache`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(cacheData)
                })
                .then(response => response.json())
                .then(data => {
                    if (data.code === 200) {
                        alert('缓存设置成功');
                        const modal = bootstrap.Modal.getInstance(document.getElementById('setCacheModal'));
                        modal.hide();
                        document.getElementById('setCacheForm').reset();
                        
                        // 搜索并显示刚设置的缓存
                        document.getElementById('searchKeyInput').value = key;
                        document.getElementById('searchCacheButton').click();
                    } else {
                        alert('设置失败: ' + (data.message || '未知错误'));
                    }
                })
                .catch(error => {
                    console.error('设置缓存失败:', error);
                    alert('设置失败: 网络错误');
                });
            });
            
            // 更新过期时间按钮事件
            document.getElementById('updateExpireButton').addEventListener('click', function() {
                const key = document.getElementById('detailCacheKey').value;
                const keyDisplay = document.getElementById('detailKeyDisplay').textContent;
                
                document.getElementById('expireCacheKey').value = key;
                document.getElementById('expireKeyDisplay').textContent = keyDisplay;
                
                const expireModal = new bootstrap.Modal(document.getElementById('setExpireModal'));
                expireModal.show();
            });
            
            // 确认设置过期时间按钮事件
            document.getElementById('confirmExpireButton').addEventListener('click', function() {
                const key = document.getElementById('expireCacheKey').value;
                const expireStr = document.getElementById('newExpireTime').value.trim();
                
                if (!expireStr) {
                    alert('请输入过期时间');
                    return;
                }
                
                const expire = parseInt(expireStr);
                
                fetch(`${baseUrl}/api/cache/${encodeURIComponent(key)}/expire`, {
                    method: 'PUT',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(expire)
                })
                .then(response => response.json())
                .then(data => {
                    if (data.code === 200) {
                        alert('过期时间设置成功');
                        const expireModal = bootstrap.Modal.getInstance(document.getElementById('setExpireModal'));
                        expireModal.hide();
                        
                        // 刷新详情
                        fetchCacheDetail(key);
                    } else {
                        alert('设置失败: ' + (data.message || '未知错误'));
                    }
                })
                .catch(error => {
                    console.error('设置过期时间失败:', error);
                    alert('设置失败: 网络错误');
                });
            });
            
            // 从详情页删除缓存按钮事件
            document.getElementById('deleteFromDetailButton').addEventListener('click', function() {
                const key = document.getElementById('detailCacheKey').value;
                deleteCache(key);
            });
            
            // 查询单个缓存
            function fetchCache(key) {
                fetch(`${baseUrl}/api/cache/${encodeURIComponent(key)}`)
                    .then(response => response.json())
                    .then(data => {
                        const tableBody = document.getElementById('cacheTableBody');
                        
                        if (data.code === 200) {
                            // 缓存存在
                            const cacheValue = data.data || '';
                            let formattedValue = cacheValue;
                            
                            // 尝试格式化JSON
                            try {
                                const parsed = JSON.parse(cacheValue);
                                formattedValue = JSON.stringify(parsed, null, 2);
                            } catch (e) {
                                // 不是有效的JSON，保持原样
                            }
                            
                            // 获取过期时间
                            fetch(`${baseUrl}/api/cache/${encodeURIComponent(key)}/expire`)
                                .then(response => response.json())
                                .then(expireData => {
                                    const expireTime = expireData.code === 200 ? expireData.data : '永不过期';
                                    
                                    tableBody.innerHTML = `
                                        <tr>
                                            <td>${key}</td>
                                            <td>
                                                <div class="code-block">${formattedValue}</div>
                                            </td>
                                            <td>${expireTime}</td>
                                            <td>
                                                <span class="badge bg-success">是</span>
                                            </td>
                                            <td>
                                                <button class="btn btn-sm btn-outline-primary me-2 get-cache" data-key="${key}">获取详情</button>
                                                <button class="btn btn-sm btn-outline-warning me-2 set-expire" data-key="${key}">设置过期时间</button>
                                                <button class="btn btn-sm btn-outline-danger delete-cache" data-key="${key}">删除缓存</button>
                                            </td>
                                        </tr>
                                    `;
                                    
                                    // 绑定事件
                                    bindCacheRowEvents();
                                });
                        } else {
                            // 缓存不存在
                            tableBody.innerHTML = `
                                <tr>
                                    <td colspan="5" class="text-center text-muted">缓存键「${key}」不存在</td>
                                </tr>
                            `;
                        }
                    })
                    .catch(error => {
                        console.error('查询缓存失败:', error);
                        const tableBody = document.getElementById('cacheTableBody');
                        tableBody.innerHTML = `
                            <tr>
                                <td colspan="5" class="text-center text-danger">查询失败，请重试</td>
                            </tr>
                        `;
                    });
            }
            
            // 获取缓存详情
            function fetchCacheDetail(key) {
                fetch(`${baseUrl}/api/cache/${encodeURIComponent(key)}`)
                    .then(response => response.json())
                    .then(data => {
                        if (data.code === 200) {
                            const cacheValue = data.data || '';
                            let formattedValue = cacheValue;
                            
                            // 尝试格式化JSON
                            try {
                                const parsed = JSON.parse(cacheValue);
                                formattedValue = JSON.stringify(parsed, null, 2);
                            } catch (e) {
                                // 不是有效的JSON，保持原样
                            }
                            
                            // 获取过期时间
                            fetch(`${baseUrl}/api/cache/${encodeURIComponent(key)}/expire`)
                                .then(response => response.json())
                                .then(expireData => {
                                    const expireTime = expireData.code === 200 ? expireData.data : '永不过期';
                                    
                                    document.getElementById('detailCacheKey').value = key;
                                    document.getElementById('detailKeyDisplay').textContent = key;
                                    document.getElementById('detailValueDisplay').textContent = formattedValue;
                                    document.getElementById('detailExpireDisplay').textContent = expireTime;
                                    document.getElementById('detailExistsDisplay').innerHTML = '<span class="badge bg-success">存在</span>';
                                });
                        }
                    });
            }
            
            // 删除缓存
            function deleteCache(key) {
                if (confirm(`确定要删除缓存键「${key}」吗？`)) {
                    fetch(`${baseUrl}/api/cache/${encodeURIComponent(key)}`, {
                        method: 'DELETE'
                    })
                    .then(response => response.json())
                    .then(data => {
                        if (data.code === 200) {
                            alert('缓存删除成功');
                            
                            // 关闭详情模态框
                            const detailModal = bootstrap.Modal.getInstance(document.getElementById('cacheDetailModal'));
                            if (detailModal) {
                                detailModal.hide();
                            }
                            
                            // 刷新表格
                            const searchKey = document.getElementById('searchKeyInput').value.trim();
                            if (searchKey === key) {
                                fetchCache(key);
                            }
                        } else {
                            alert('删除失败: ' + (data.message || '未知错误'));
                        }
                    })
                    .catch(error => {
                        console.error('删除缓存失败:', error);
                        alert('删除失败: 网络错误');
                    });
                }
            }
            
            // 绑定缓存行操作事件
            function bindCacheRowEvents() {
                // 获取详情按钮
                document.querySelectorAll('.get-cache').forEach(btn => {
                    btn.addEventListener('click', function() {
                        const key = this.getAttribute('data-key');
                        fetchCacheDetail(key);
                        const detailModal = new bootstrap.Modal(document.getElementById('cacheDetailModal'));
                        detailModal.show();
                    });
                });
                
                // 设置过期时间按钮
                document.querySelectorAll('.set-expire').forEach(btn => {
                    btn.addEventListener('click', function() {
                        const key = this.getAttribute('data-key');
                        document.getElementById('expireCacheKey').value = key;
                        document.getElementById('expireKeyDisplay').textContent = key;
                        
                        const expireModal = new bootstrap.Modal(document.getElementById('setExpireModal'));
                        expireModal.show();
                    });
                });
                
                // 删除缓存按钮
                document.querySelectorAll('.delete-cache').forEach(btn => {
                    btn.addEventListener('click', function() {
                        const key = this.getAttribute('data-key');
                        deleteCache(key);
                    });
                });
            }
            
            // 初始绑定示例行的事件
            bindCacheRowEvents();
        });
    </script>
</body>
</html>